package com.example.mdc.logback.common.aspect;

import com.example.mdc.logback.common.constant.Constant;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @author:      liu_pc
 * Date:        2023/8/23
 * Description: 动态组装异常注解实现
 * Version:     1.0
 */
@Aspect
@Component
public class BusinessAlertAspect {

    @Pointcut("@annotation(com.example.mdc.logback.common.annotation.BusinessAlert)")
    public void businessAlertPointcut() {
    }


    @AfterThrowing(pointcut = "businessAlertPointcut()", throwing = "ex")
    public void handleBusinessAlert(JoinPoint joinPoint, Exception ex) {
        // 获取方法签名和参数
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

        // 获取全局链路ID，可以根据实际情况从上下文中获取
        String globalId = getGlobalId();

        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();

        // 使用SpEL表达式动态组装异常信息的各部分
        String exceptionMessage = String.format("Method: %s, Args: %s%nMessages: %s%nGlobal ID: %s%nTime: %s",
                methodName, argsToString(args), ex.getMessage(), globalId, now);

        // 发送业务报警，可以根据实际需求进行具体实现
        sendBusinessAlert(exceptionMessage);
    }

    private String argsToString(Object[] args) {
        // 将方法参数转换为字符串表示
        // 在实际应用中，可以根据参数类型进行定制化的转换逻辑
        StringBuilder sb = new StringBuilder();
        for (Object arg : args) {
            sb.append(arg.toString()).append(", ");
        }
        return sb.toString();
    }

    private String getGlobalId() {
        // 实现获取全局链路ID的逻辑，可以从上下文、请求头等获取
        return MDC.get(Constant.TRACE_ID);
    }

    private void sendBusinessAlert(String message) {
        // 实现具体的业务报警逻辑，可以是发送邮件、短信、通知等方式
        System.out.println("Business Alert: " + message);
    }
}
